package com.chenfei.sharding.jdbc.controller;

import com.chenfei.vo.EsIndex;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import io.searchbox.client.JestClient;
import io.searchbox.client.JestResult;
import io.searchbox.core.*;
import io.searchbox.indices.CreateIndex;
import io.searchbox.indices.DeleteIndex;
import io.searchbox.indices.IndicesExists;
import io.searchbox.indices.aliases.AddAliasMapping;
import io.searchbox.indices.aliases.ModifyAliases;
import io.searchbox.indices.mapping.GetMapping;
import io.searchbox.indices.mapping.PutMapping;
import lombok.extern.slf4j.Slf4j;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

/**
 * @author chenfei
 * @description
 * @since 2018/3/26
 */
@RestController
@Slf4j
public class SearchController {
    @Autowired
    JestClient jestClient;

    @RequestMapping(value = "/search")
    public Object search(@RequestParam String indexName,@RequestParam String indexType) throws Exception{
        SearchSourceBuilder searchSourceBuilder = SearchSourceBuilder.searchSource().fetchSource(true);
        Search.Builder builder = new Search.Builder(searchSourceBuilder.toString()).addIndex(indexName);
        if (indexType != null && !indexType.isEmpty()) {
            builder.addType(indexType);
        }
        Search search = builder.build();
        SearchResult result = jestClient.execute(search);
        return result.getSourceAsString();
    }
    @RequestMapping(value = "/mappering")
    public String getMappingString(@RequestParam String indexName, @RequestParam String typeName) throws Exception{
        io.searchbox.indices.mapping.GetMapping.Builder builder = new GetMapping.Builder();
        builder.addIndex(indexName).addType(typeName);
        JestResult result = jestClient.execute(builder.build());
        if (result != null && result.isSucceeded()) {
            return result.getSourceAsObject(JsonObject.class).toString();
        }
        return null;
    }

    @RequestMapping(value = "/create/data")
    public Object test(@RequestBody EsIndex index) throws IOException {
        Bulk.Builder bulkBuilder = new Bulk.Builder();
        // 添加数据
        bulkBuilder.addAction(new Index.Builder(index.getSource()).index(index.getIndexName()).type(index.getIndexType()).build());
        long start = System.currentTimeMillis();
        BulkResult result = jestClient.execute(bulkBuilder.build());
        long end = System.currentTimeMillis();
        log.info("elasticsearch批量插入-->> {}毫秒", (end - start) );
        List<BulkResult.BulkResultItem> failedItems = result.getFailedItems();

        return result.getItems();
    }
    @RequestMapping(value = "/doc",method = RequestMethod.POST)
    public boolean insertOrUpdateDoc(@RequestBody EsIndex esIndex) throws Exception{
        Index.Builder builder = new Index.Builder(esIndex.getSource());
        builder.id(esIndex.getId());
        Index index = builder.index(esIndex.getIndexName()).type(esIndex.getIndexType()).build();
        long start = System.currentTimeMillis();
        JestResult result = jestClient.execute(index);
        if (result != null && result.isSucceeded()) {
            long end = System.currentTimeMillis();
            log.info("插入更新文档时间: -->> " + (end - start) + " 毫秒");
            return true;
        }
        log.warn("插入更新文档失败:"+ result.getErrorMessage());
        return false;
    }

    @RequestMapping(value = "/index",method = RequestMethod.POST)
    public Object createIndex(@RequestParam String indexName) throws Exception {
        if(!isIndexExist(indexName)){
            CreateIndex createIndex = new CreateIndex.Builder(indexName).build();
            JestResult result = jestClient.execute(createIndex);
            if (result != null && result.isSucceeded()) {
                return true;
            }
            log.warn("创建索引失败:"+ result.getErrorMessage());
            return false;
        }else{
            log.warn("索引存在");
            return true;
        }

    }
    @RequestMapping(value = "/index",method = RequestMethod.DELETE)
    public boolean deleteIndex(@RequestParam String indexName) throws Exception{
        DeleteIndex delete = new DeleteIndex.Builder(indexName).build();
        JestResult result = jestClient.execute(delete);
        if (result != null && result.isSucceeded()) {
            return true;
        }
        log.warn("删除索引失败:"+ result.getErrorMessage());
        return false;
    }

    @RequestMapping(value = "/alias",method= RequestMethod.POST)
    public boolean addAlias(@RequestParam String indexName,@RequestParam String alias) throws Exception{
        AddAliasMapping addAliasMapping = new AddAliasMapping.Builder(indexName, alias).build();
        ModifyAliases modifyAliases = new ModifyAliases.Builder(addAliasMapping).build();
        JestResult result = jestClient.execute(modifyAliases);
        if (result != null && result.isSucceeded()) {
            return true;
        }
        log.warn("添加别名失败:"+ result.getErrorMessage());
        return false;
    }
    @RequestMapping(value = "/alias",method= RequestMethod.GET)
    public List<String> searchIndexByAlias(String alias) throws Exception {
        Cat cat = new Cat.AliasesBuilder().addIndex(alias).build();
        CatResult result = jestClient.execute(cat);
        if (result != null && result.isSucceeded()) {
            JsonObject jsonObject = result.getJsonObject();
            List<String> indexNames = new ArrayList<String>();
            if (jsonObject != null && jsonObject.get("result") != null && jsonObject.get("result").isJsonArray()) {
                JsonArray asJsonArray = jsonObject.get("result").getAsJsonArray();
                for (JsonElement jsonElement : asJsonArray) {
                    JsonElement element = jsonElement.getAsJsonObject().get("index");
                    if (element != null ) {
                        indexNames.add(element.getAsString());
                    }
                }
            }
            return indexNames;
        }
        return null;
    }


    @RequestMapping(value = "/type")
    public boolean createType(@RequestParam String indexName,@RequestParam String indexType,@RequestParam String mappingString) throws Exception{
        PutMapping.Builder builder = new PutMapping.Builder(indexName, indexType, mappingString);
        JestResult result = jestClient.execute(builder.build());
        if (result != null && result.isSucceeded()) {
            return true;
        }
        log.warn("创建索引类型失败:"+ result.getErrorMessage());
        return false;
    }

    private boolean isIndexExist(String indexName) throws Exception{
        IndicesExists.Builder builder = new IndicesExists.Builder(indexName);
        JestResult result = jestClient.execute(builder.build());
        if (result != null && result.isSucceeded()) {
            return true;
        }
        return false;
    }
}
